home *** CD-ROM | disk | FTP | other *** search
- From: argv@zipcode.com (Dan Heller)
- Newsgroups: comp.sources.misc
- Subject: v18i078: mush - Mail User's Shell, Part21/22
- Message-ID: <1991Apr22.153932.380@sparky.IMD.Sterling.COM>
- Date: 22 Apr 91 15:39:32 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 80edc9a2 631f45a7 27f6cee2 bfdb090f
-
- Submitted-by: Dan Heller <argv@zipcode.com>
- Posting-number: Volume 18, Issue 78
- Archive-name: mush/part21
- Supersedes: mush: Volume 12, Issue 28-47
-
- #!/bin/sh
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file signals.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 21; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping signals.c'
- else
- echo 'x - continuing file signals.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'signals.c' &&
- X (void) fprintf(stderr, "%s: %s\n", prog_name,
- X (sig == SIGSEGV)? "Segmentation violation": "Bus error");
- X cleanup(sig);
- }
- SHAR_EOF
- echo 'File signals.c is complete' &&
- chmod 0644 signals.c ||
- echo 'restore of signals.c failed'
- Wc_c="`wc -c < 'signals.c'`"
- test 12425 -eq "$Wc_c" ||
- echo 'signals.c: original size 12425, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= sort.c ==============
- if test -f 'sort.c' -a X"$1" != X"-c"; then
- echo 'x - skipping sort.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting sort.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'sort.c' &&
- /* sort.c 3.0 (c) copyright 1986,1990 (Dan Heller) */
- X
- #include "mush.h"
- /* #define MYQSORT */
- X
- /* The size of this array should really be bounded by
- X * 2 spaces for each possible different sort criteria
- X * (one space for each key letter and one per for 'r'),
- X * but 16 leaves room to add to the current list.
- X */
- static char subsort[16];
- X
- static int depth, order, ignore_case;
- static jmp_buf sortbuf;
- X
- sort(argc, argv, list)
- register int argc;
- register char *argv[], list[];
- {
- X int msg_cmp();
- X SIGRET (*oldint)(), (*oldquit)();
- X int n, offset = -1, range = 0;
- X long curr_msg_off = msg[current_msg].m_offset;
- X
- X depth = 0, order = 1, ignore_case = FALSE;
- X
- X while (argc && *++argv) {
- X n = (argv[0][0] == '-' && argv[0][1] != 0);
- X while (argv[0][n]) {
- X if (depth > sizeof subsort - 2)
- X break;
- X switch(argv[0][n]) {
- X case '-': /* reverse order of next criteria (obsolete) */
- X argv[0][n] = 'r'; /* fix it and fall through */
- X case 'r': /* reverse order of next criteria */
- X case 'd': /* sort by date */
- X case 'a': /* sort by author (address) */
- X case 's': /* sort by subject (ignore Re:) */
- X case 'R': /* sort by subject including Re: */
- X case 'l': /* sort by length in bytes */
- X case 'S': /* sort by message status */
- X case 'p': /* sort by message priority */
- X /* skip consecutive repeats of the same flag */
- X if (depth < 1 || subsort[depth-1] != argv[0][n])
- X subsort[depth++] = argv[0][n];
- X when 'i': ignore_case = TRUE;
- X otherwise: return help(0, "sort", cmd_help);
- X }
- X n++;
- X }
- X }
- X if (depth == 0 || subsort[depth-1] == 'r')
- X subsort[depth++] = 'S'; /* status sort is the default */
- X subsort[depth] = 0;
- X depth = 0; /* start at the beginning */
- X if (msg_cnt <= 1) {
- X print("Not enough messages to sort.\n");
- X return -1;
- X }
- X turnon(glob_flags, IGN_SIGS);
- X on_intr();
- X
- X if (list && ison(glob_flags, IS_PIPE)) {
- X int consec = 1;
- X for (n = 0; n < msg_cnt; n++)
- X if (msg_bit(list, n)) {
- X if (!consec) {
- X ok_box("Listed messages not consecutive\n");
- X turnoff(glob_flags, IGN_SIGS);
- X off_intr();
- X return -1;
- X }
- X if (offset < 0)
- X offset = n;
- X range++;
- X } else if (offset >= 0)
- X consec = 0;
- X } else
- X offset = 0, range = msg_cnt;
- X
- X if (range < 2)
- X print("Range not broad enough to sort anything\n");
- X else {
- X Debug("Sorting %d messages starting at message %d\n", range, offset+1);
- X
- X if (setjmp(sortbuf) == 0)
- X qsort((char *)&msg[offset], range, sizeof (struct msg), msg_cmp);
- X else
- X print("WARNING: Sorting interrupted: unpredictable order.\n");
- X turnon(glob_flags, DO_UPDATE);
- X }
- X for (n = 0; n < msg_cnt; n++)
- X if (msg[n].m_offset == curr_msg_off)
- X break;
- X current_msg = n;
- X turnoff(glob_flags, IGN_SIGS);
- X off_intr();
- X /* Break pipes because message lists are invalid */
- X return 0 - in_pipe();
- }
- X
- #ifdef MYQSORT
- qsort(base, len, siz, compar)
- register struct msg *base;
- int (*compar)();
- {
- X register int i, swapping;
- X struct msg temp;
- X
- X do {
- X swapping = 0;
- X for (i = 0; i < len-1; ++i) {
- X if (compar(base+i, base+i+1) > 0) {
- X temp = base[i];
- X base[i] = base[i+1];
- X base[i+1] = temp;
- X swapping = 1;
- X }
- X }
- X } while (swapping);
- }
- #endif /* MYSORT */
- X
- status_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X if (msg1->m_flags == msg2->m_flags)
- X return msg_cmp(msg1, msg2);
- X if (ison(msg1->m_flags, DELETE) && isoff(msg2->m_flags, DELETE))
- X return order;
- X if (isoff(msg1->m_flags, DELETE) && ison(msg2->m_flags, DELETE))
- X return -order;
- X if (isoff(msg1->m_flags, OLD) && ison(msg2->m_flags, OLD))
- X return -order;
- X if (ison(msg1->m_flags, OLD) && isoff(msg2->m_flags, OLD))
- X return order;
- X if (ison(msg1->m_flags, UNREAD) && isoff(msg2->m_flags, UNREAD))
- X return -order;
- X if (isoff(msg1->m_flags, UNREAD) && ison(msg2->m_flags, UNREAD))
- X return order;
- X if (ison(msg1->m_flags,PRESERVE) && isoff(msg2->m_flags,PRESERVE))
- X return -order;
- X if (isoff(msg1->m_flags,PRESERVE) && ison(msg2->m_flags,PRESERVE))
- X return order;
- X if (ison(msg1->m_flags,REPLIED) && isoff(msg2->m_flags,REPLIED))
- X return -order;
- X if (isoff(msg1->m_flags,REPLIED) && ison(msg2->m_flags,REPLIED))
- X return order;
- X if (ison(msg1->m_flags,SAVED) && isoff(msg2->m_flags,SAVED))
- X return -order;
- X if (isoff(msg1->m_flags,SAVED) && ison(msg2->m_flags,SAVED))
- X return order;
- X if (ison(msg1->m_flags,PRINTED) && isoff(msg2->m_flags,PRINTED))
- X return -order;
- X if (isoff(msg1->m_flags,PRINTED) && ison(msg2->m_flags,PRINTED))
- X return order;
- X if (ison(msg1->m_flags,FORWARD) && isoff(msg2->m_flags,FORWARD))
- X return -order;
- X if (isoff(msg1->m_flags,FORWARD) && ison(msg2->m_flags,FORWARD))
- X return order;
- X
- X return pri_cmp(msg1, msg2);
- }
- X
- author_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X char buf1[HDRSIZ], buf2[HDRSIZ];
- X int retval;
- X
- X (void) reply_to(msg1 - msg, 0, buf1); /* "0" for "author only" */
- X (void) reply_to(msg2 - msg, 0, buf2);
- X Debug("author: msg %d: %s, msg %d: %s\n", msg1-msg, buf1, msg2-msg, buf2);
- X if (ignore_case)
- X retval = lcase_strncmp(buf1, buf2, -1) * order;
- X else
- X retval = strcmp(buf1, buf2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- }
- X
- /* compare messages according to size (length) */
- size_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X int retval;
- X
- X Debug("sizes: (%d): %d, (%d): %d\"\n",
- X msg1-msg, msg1->m_size, msg2-msg, msg2->m_size);
- X if (retval = (msg1->m_size - msg2->m_size) * order) /* assign and test */
- X return retval;
- X return msg_cmp(msg1, msg2);
- }
- X
- /*
- X * Subject comparison ignoring Re: subject_to() appends an Re: if there is
- X * any subject whatsoever.
- X */
- subject_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X char buf1[HDRSIZ], buf2[HDRSIZ];
- X register char *p1, *p2;
- X int retval;
- X
- X p1 = subject_to(msg1 - msg, buf1);
- X p2 = subject_to(msg2 - msg, buf2);
- X if (p1) {
- X p1 += 4;
- X while (isspace(*p1))
- X p1++;
- X } else
- X p1 = buf1; /* subject_to() makes it an empty string */
- X if (p2) {
- X p2 += 4;
- X while (isspace(*p2))
- X p2++;
- X } else
- X p2 = buf2; /* subject_to() makes it an empty string */
- X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n", msg1-msg, p1, msg2-msg, p2);
- X if (ignore_case)
- X retval = lcase_strncmp(p1, p2, -1) * order;
- X else
- X retval = strcmp(p1, p2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- }
- X
- /*
- X * compare subject strings from two messages.
- X * If Re is appended, so be it -- if user wants to ignore Re: use 'R' flag.
- X */
- subj_with_re(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X char buf1[HDRSIZ], buf2[HDRSIZ], *p;
- X int retval;
- X
- X if (!(p = header_field(msg1 - msg, "subject")))
- X p = "";
- X (void) strcpy(buf1, p);
- X if (!(p = header_field(msg2 - msg, "subject")))
- X p = "";
- X (void) strcpy(buf2, p);
- X Debug("subjects: (%d): \"%s\" (%d): \"%s\"\n",
- X msg1-msg, buf1, msg2-msg, buf2);
- X if (ignore_case)
- X retval = lcase_strncmp(buf1, buf2, -1) * order;
- X else
- X retval = strcmp(buf1, buf2) * order;
- X return retval ? retval : msg_cmp(msg1, msg2);
- }
- X
- date_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X long tm1, tm2;
- X
- X if (ison(glob_flags, DATE_RECV)) {
- X (void) sscanf(msg1->m_date_recv, "%ld", &tm1);
- X (void) sscanf(msg2->m_date_recv, "%ld", &tm2);
- X } else {
- X (void) sscanf(msg1->m_date_sent, "%ld", &tm1);
- X (void) sscanf(msg2->m_date_sent, "%ld", &tm2);
- X }
- X return tm1 < tm2 ? -order : (tm1 > tm2) ? order : msg_cmp(msg1, msg2);
- }
- X
- pri_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X int i;
- X u_long pr1 = 0, pr2 = 0;
- X
- X for (i = 0; pr1 == pr2 && i <= MAX_PRIORITY; i++) {
- X if (ison(msg1->m_flags, M_PRIORITY(i)))
- X turnon(pr1, ULBIT(i));
- X if (ison(msg2->m_flags, M_PRIORITY(i)))
- X turnon(pr2, ULBIT(i));
- X }
- X return pr1 > pr2 ? -order : (pr1 < pr2) ? order : msg_cmp(msg1, msg2);
- }
- X
- static
- msg_cmp(msg1, msg2)
- register struct msg *msg1, *msg2;
- {
- X int sv_order = order, sv_depth = depth, retval = 0;
- X
- X if (ison(glob_flags, WAS_INTR))
- X longjmp(sortbuf, 1);
- X if (msg1 < msg || msg2 < msg) {
- X wprint("sort botch trying to sort %d and %d using %s\n",
- X msg1-msg, msg2-msg, subsort);
- X return 0;
- X }
- X
- X if (subsort[depth] == 'r') {
- X order = -1;
- X depth++;
- X } else
- X order = 1;
- X switch(subsort[depth++]) {
- X case '\0': retval = 0;
- X when 'd': retval = date_cmp(msg1, msg2);
- X when 'a': retval = author_cmp(msg1, msg2);
- X when 's': retval = subject_cmp(msg1, msg2);
- X when 'R': retval = subj_with_re(msg1, msg2);
- X when 'l': retval = size_cmp(msg1, msg2); /* length compare */
- X when 'p': retval = pri_cmp(msg1, msg2);
- X otherwise: retval = status_cmp(msg1, msg2);
- X }
- X depth = sv_depth;
- X order = sv_order;
- X return retval;
- }
- SHAR_EOF
- chmod 0644 sort.c ||
- echo 'restore of sort.c failed'
- Wc_c="`wc -c < 'sort.c'`"
- test 8699 -eq "$Wc_c" ||
- echo 'sort.c: original size 8699, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= strings.c ==============
- if test -f 'strings.c' -a X"$1" != X"-c"; then
- echo 'x - skipping strings.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting strings.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'strings.c' &&
- /* strings.c Copyright(1988) Dan Heller */
- X
- #include "mush.h"
- X
- /*
- X * reverse a string. Useful for uucp-style address comparisons.
- X */
- char *
- reverse(s)
- char s[];
- {
- X int n = strlen(s), m;
- X char c;
- X
- X if (n < 1)
- X return 0;
- X if (n & 1)
- X n = n/2 + 1, m = n - 2;
- X else
- X n /= 2, m = n - 1;
- X for ( ; m >= 0; m--, n++)
- X c = s[n], s[n] = s[m], s[m] = c;
- X return s;
- }
- X
- /*
- X * lose the newline character, trailing whitespace, and return the end of p
- X * test for '\n' separately since some _ctype_[] arrays may not have the
- X * _S bit set for the newline character. see <ctype.h> for more info.
- X */
- char *
- no_newln(p)
- register char *p;
- {
- X register char *p2 = p + strlen(p); /* point it to the null terminator */
- X
- X while (p2 > p && *--p2 == '\n' || isspace(*p2))
- X *p2 = 0; /* get rid of newline and trailing spaces */
- X return p2;
- }
- X
- /* find any character in s1 that's in s2; return pointer to char in s1. */
- char *
- any(s1, s2)
- register char *s1, *s2;
- {
- X register char *p;
- X if (!s1 || !*s1 || !s2 || !*s2)
- X return NULL;
- X for( ; *s1; s1++) {
- X for(p = s2; *p; p++)
- X if (*p == *s1)
- X return s1;
- X }
- X return NULL;
- }
- X
- /* check two lists of strings each of which contain substrings.
- X * Each substring is delimited by any char in "delimiters"
- X * return true if any elements in list1 are on list2.
- X * thus:
- X * string1 = "foo, bar, baz"
- X * string2 = "foobar, baz, etc"
- X * delimiters = ", \t"
- X * example returns 1 because "baz" exists in both lists
- X * NOTE: case is ignored.
- X */
- chk_two_lists(list1, list2, delimiters)
- register char *list1, *list2, *delimiters;
- {
- X register char *p, c;
- X register int found = 0;
- X
- X if (!list1 || !list2)
- X return 0;
- X
- X if (p = any(list1, delimiters)) {
- X if (p > list1) {
- X c = *p; *p = 0;
- X /* Check list2 against the first word of list1.
- X * Swap places of list2 and list1 to step through list2.
- X */
- X found = chk_two_lists(list2, list1, delimiters);
- X *p = c;
- X }
- X if (found)
- X return 1;
- X for (p++; *p && index(delimiters, *p); p++)
- X ;
- X if (!*p)
- X return 0;
- X } else if (!any(list2, delimiters))
- X /* Do the trivial case of single words */
- X return !lcase_strncmp(list1, list2, -1);
- X else
- X p = list1;
- X
- X /* Either only list2 has delims or the first word of list1
- X * did not match anything in list2. Check list2 against the
- X * rest of list1. This could be more efficient by using a
- X * different function to avoid repeating the any() calls.
- X */
- X return chk_two_lists(list2, p, delimiters);
- }
- X
- bzero(addr, size)
- register char *addr;
- register int size;
- {
- X while (size-- > 0)
- X addr[size] = 0;
- }
- X
- /* do an atoi() on the string passed and return in "val" the decimal value.
- X * the function returns a pointer to the location in the string that is not
- X * a digit.
- X */
- char *
- my_atoi(p, val)
- register char *p;
- register int *val;
- {
- X int positive = 1;
- X
- X if (!p)
- X return NULL;
- X *val = 0;
- X if (*p == '-')
- X positive = -1, p++;
- X while (isdigit(*p))
- X *val = (*val) * 10 + *p++ - '0';
- X *val *= positive;
- X return p;
- }
- X
- /* strcmp ignoring case */
- lcase_strncmp(str1, str2, n)
- register char *str1, *str2;
- {
- X while (*str1 && *str2 && --n != 0)
- X if (lower(*str1) != lower(*str2))
- X break;
- X else
- X str1++, str2++;
- X return lower(*str1) - lower(*str2);
- }
- X
- /* strcpy converting everything to lower case (arbitrary) to ignore cases */
- char *
- lcase_strcpy(dst, src)
- register char *dst, *src;
- {
- X register char *s = dst;
- X
- X /* "lower" is a macro, don't increment its argument! */
- X while (*dst++ = lower(*src))
- X src++;
- X return s;
- }
- X
- /* this strcpy returns number of bytes copied */
- Strcpy(dst, src)
- register char *dst, *src;
- {
- X register int n = 0;
- X if (!dst || !src)
- X return 0;
- X while (*dst++ = *src++)
- X n++;
- X return n;
- }
- X
- char *
- savestr(s)
- register char *s;
- {
- X register char *p;
- X
- X if (!s)
- X s = "";
- X if (!(p = malloc((unsigned) (strlen(s) + 1)))) {
- X error("out of memory saving %s", s);
- X return NULL;
- X }
- X return strcpy(p, s);
- }
- X
- /* copy a vector of strings into one string -- return the end of the string */
- char *
- argv_to_string(p, argv)
- register char *p, **argv;
- {
- X register int i;
- X register char *ptr = p;
- X
- X *p = 0;
- X if (!argv[0])
- X return "";
- X for (i = 0; argv[i]; i++)
- X ptr += strlen(sprintf(ptr, "%s ", argv[i]));
- X *--ptr = 0; /* get rid of the last space */
- X return ptr;
- }
- X
- char *
- itoa(n)
- {
- X static char buf[10];
- X return sprintf(buf, "%d", n);
- }
- X
- /*
- X * There are two different kinds of sprintf() --those that return char * and
- X * those that return int. System-V returns int (the length of the resulting
- X * string). BSD has historically returned a pointer to the resulting string
- X * instead. Mush was originally written under BSD, so the usage has always
- X * been to assume the char * method. Because the system-v method is far more
- X * useful, mush should some day change to use that method, but until then,
- X * this routine was written to allow all the unix'es to appear the same to
- X * the programmer regardless of which sprintf is actually used. The "latest"
- X * version of 4.3BSD (as of Fall 1988) has changed its format to go from the
- X * historical BSD method to the sys-v method. It is no longer possible to
- X * simply #ifdef this routine for sys-v --it is now required to use this
- X * routine regardless of which sprintf is notice to your machine. However,
- X * if you know your system's sprintf returns a char *, you can remove the
- X * define in strings.h
- X */
- #include <varargs.h>
- /*VARARGS*/
- /*ARGSUSED*/
- char *
- Sprintf(va_alist)
- va_dcl
- {
- X char *buf, *fmt;
- X va_list ap;
- X
- X va_start(ap);
- X buf = va_arg(ap, char *);
- X fmt = va_arg(ap, char *);
- #ifdef VPRINTF
- X (void) vsprintf(buf, fmt, ap);
- #else
- X {
- X FILE foo;
- X foo._cnt = BUFSIZ;
- X foo._base = foo._ptr = buf; /* may have to be cast (unsigned char *) */
- X foo._flag = _IOWRT+_IOSTRG;
- X (void) _doprnt(fmt, ap, &foo);
- X *foo._ptr = '\0'; /* plant terminating null character */
- X }
- #endif /* VPRINTF */
- X va_end(ap);
- X return buf;
- }
- X
- void
- print_argv(argv)
- char **argv;
- {
- X while (*argv)
- X if (debug)
- X wprint("(%s) ", *argv++);
- X else
- X wprint("%s ", *argv++);
- X wprint("\n");
- }
- X
- /*
- X * putstring -- put a string into a file. Expand \t's into tabs and \n's
- X * into newlines. Append a \n and fflush(fp);
- X */
- void
- putstring(p, fp)
- register char *p;
- register FILE *fp;
- {
- X for ( ; *p; ++p)
- X if (*p != '\\')
- X (void) fputc(*p, fp);
- X else
- X switch(*++p) {
- X case 'n': (void) fputc('\n', fp);
- X when 't': (void) fputc('\t', fp);
- X otherwise: (void) fputc(*p, fp);
- X }
- X (void) fputc('\n', fp);
- X (void) fflush(fp);
- }
- X
- #define chtoi(c) ((int)(c) - (int)'0')
- X
- /* m_xlate(str) converts strings of chars which contain ascii representations
- X * of control characters appearing in str into the literal characters they
- X * represent. The usual curses-mode character expansions (\Cx -> control-x)
- X * are honored, as are most C escapes. Unrecognized portions are unchanged.
- X */
- char *
- m_xlate (str)
- register char *str;
- {
- X register char *r, *s, *t;
- X int dv, nd;
- X
- X /*
- X * r will receive the new string, s will track the old one,
- X * and t will step through escape sequences
- X * This allows the translation to be done in place
- X */
- X r = s = str;
- X while (s && *s) {
- X if (*s == '\\') {
- X t = s + 1;
- X /*
- X * After each case below, t should point to the character
- X * following the escape sequence
- X */
- X switch(*t) {
- X case '\0' :
- X /*
- X * Hmmm ... a backslash followed by the string
- X * terminator. Copy the backslash ONLY.
- X */
- X *r++ = *s++;
- X break;
- X case '0' :
- X case '1' :
- X case '2' :
- X case '3' :
- X case '4' :
- X case '5' :
- X case '6' :
- X case '7' :
- X /*
- X * Convert up to 3 octal digits to their ascii value
- X */
- X dv = chtoi(*t++);
- X for (nd = 0; (isdigit(*t) && (nd < 2)); nd++)
- X if (chtoi(*t) < 8)
- X dv = (8 * dv) + chtoi(*t++);
- X else
- X break;
- X if (dv < 256 && dv > 0)
- X /* Valid octal number escaped */
- X *r++ = (char)dv;
- X else
- X /* Invalid octal number, so copy unchanged */
- X while (s < t)
- X *r++ = *s++;
- X break;
- X case 'b' :
- X *r++ = '\b';
- X t++;
- X break;
- X case 'C' :
- X t++;
- X if (*t == '?')
- X *r++ = '\177';
- X else if (*t == '~')
- X *r++ = '\036';
- X else if (*t == '/')
- X *r++ = '\037';
- X else if (isalpha(*t) || *t > '\132' && *t < '\140')
- X *r++ = *t & 037;
- X else
- X while (s <= t) *r++ = *s++;
- X t++;
- X break;
- X case 'E' :
- X *r++ = '\033';
- X t++;
- X break;
- X case 'f' :
- X *r++ = '\f';
- X t++;
- X break;
- X case 'n' :
- X *r++ = '\n';
- X t++;
- X break;
- X case 'r' :
- X *r++ = '\r';
- X t++;
- X break;
- X case 't' :
- X *r++ = '\t';
- X t++;
- X break;
- X case '\\' :
- X *r++ = *t++;
- X break;
- X default :
- X /*
- X * Not recognized, so copy both characters
- X */
- X *r++ = *s++;
- X *r++ = *s++;
- X break;
- X }
- X /*
- X * Now make sure s also points to the character after the
- X * escape sequence, by comparing to t
- X */
- X if (t > s)
- X s = t;
- X } else
- X *r++ = *s++;
- X }
- X *r = '\0';
- X return str;
- }
- X
- /*
- X * Convert control characters to ascii format (reverse effect of m_xlate()).
- X */
- char *
- ctrl_strcpy(s_out, s_in, bind_format)
- register char *s_out, *s_in;
- {
- #if !defined(M_XENIX) || (defined(M_XENIX) && !defined(CURSES))
- X extern char *_unctrl[];
- #endif /* !M_XENIX || M_XENIX && !CURSES */
- X char *start = s_out;
- X
- X for (; *s_in; s_in++)
- X if (*s_in == '\n')
- X *s_out++ = '\\', *s_out++ = 'n';
- X else if (*s_in == '\r')
- X *s_out++ = '\\', *s_out++ = 'r';
- X else if (*s_in == '\t')
- X *s_out++ = '\\', *s_out++ = 't';
- X else if (*s_in == ESC)
- X *s_out++ = '\\', *s_out++ = 'E';
- X else if (iscntrl(*s_in)) {
- X if (bind_format)
- X *s_out++ = '\\', *s_out++ = 'C';
- X else
- X *s_out++ = '^';
- X *s_out++ = _unctrl[*s_in][1];
- X } else
- X *s_out++ = *s_in;
- X *s_out = 0;
- X return start;
- }
- X
- /*
- X * This routine returns a pointer to the file portion of a path/file name.
- X */
- char *
- basename(path)
- register char *path;
- {
- X char *file;
- X
- X if (file = rindex(path, '/'))
- X return ++file;
- X return path;
- }
- SHAR_EOF
- chmod 0644 strings.c ||
- echo 'restore of strings.c failed'
- Wc_c="`wc -c < 'strings.c'`"
- test 10202 -eq "$Wc_c" ||
- echo 'strings.c: original size 10202, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= strings.h ==============
- if test -f 'strings.h' -a X"$1" != X"-c"; then
- echo 'x - skipping strings.h (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting strings.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'strings.h' &&
- /* @(#)strings.h (c) copyright 9/3/86 (Dan Heller) */
- X
- /*
- X * If you *know* your sprintf() returns char*, you can remove the follow
- X * define. Careful, "new" 4.3BSD's sprintf returns int. See README
- X */
- #define sprintf Sprintf
- #ifdef SYSV
- #define index strchr
- #define rindex strrchr
- #endif /* SYSV */
- X
- /* External function definitions for routines described in string(3). */
- extern char
- X *strcat(), *strncat(), *strcpy(), *strncpy(),
- X *index(), *rindex(), *getenv();
- extern int
- X strcmp(), strncmp(), strlen();
- X
- extern char
- X *Sprintf(), /* See comments above function in strings.c */
- X *argv_to_string(), /* convert a vector of strings into one string */
- X *any(), /* return first char in str2 that exists in str1 */
- X *basename(), /* return the last component of a file path */
- X *ctrl_strcpy(), /* string copy converting control chars to ascii */
- X *itoa(), /* return a string representation of a number */
- X *lcase_strcpy(), /* just like strcpy, but convert all chars to lower */
- X *m_xlate(), /* translate string from ascii to ctrl-char format */
- X *my_atoi(), /* do an atoi, but return the last char parsed */
- X *no_newln(), /* remove newline and extra whitespace - return end */
- X *savestr(); /* strcpy arg into malloc-ed memory; return address */
- X
- extern void
- X print_argv(), /* prints an argv as one string */
- X putstring(); /* put a string */
- SHAR_EOF
- chmod 0644 strings.h ||
- echo 'restore of strings.h failed'
- Wc_c="`wc -c < 'strings.h'`"
- test 1396 -eq "$Wc_c" ||
- echo 'strings.h: original size 1396, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= tool.c ==============
- if test -f 'tool.c' -a X"$1" != X"-c"; then
- echo 'x - skipping tool.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting tool.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'tool.c' &&
- /* @(#)tool.c (c) copyright 10/15/86 (Dan Heller) */
- X
- /* tool.c --make the mailtool windows, panels, etc... */
- #include "mush.h"
- X
- #ifndef FONTDIR
- #define FONTDIR "/usr/lib/fonts/fixedwidthfonts/"
- #endif /* FONTDIR */
- X
- extern void print_sigwinch(), make_hdr_sw();
- extern Notify_value fkey_interposer();
- X
- static void init_cursors(), geticon();
- X
- extern Panel /* panels.c */
- X make_hdr_panel(), make_main_panel();
- X
- Panel
- X main_panel, /* the main panel dealing with generic items */
- X hdr_panel; /* panel which contains message header specific items */
- X
- Textsw mfprint_sw;
- Frame compose_frame;
- int compose_destroy = 0;
- X
- static char **choice_args, **button_args;
- X
- short dat_mail_icon_1[] = {
- #include "mail.icon.1"
- };
- X
- short dat_mail_icon_2[] = {
- #include "mail.icon.2"
- };
- X
- short dat_compose_icon[] = {
- #include "compose.icon"
- };
- X
- short dat_coffee_cup[] = {
- X 0x0200,0x0100,0x0600,0x0800,0x0600,0x0100,0xFFF8,0x800C,
- X 0x800A,0x4012,0x401C,0x2020,0x9048,0x7FF0,0x3FE0,0x0000
- };
- X
- mpr_static(mail_icon_image1, 64, 64, 1, dat_mail_icon_1);
- mpr_static(mail_icon_image2, 64, 64, 1, dat_mail_icon_2);
- mpr_static(compose_icon_image, 64, 64, 1, dat_compose_icon);
- X
- mpr_static(coffee_cup, 16, 16, 1, dat_coffee_cup);
- X
- /* public for hdr_sw.c */
- Cursor l_cursor, m_cursor, r_cursor;
- static Cursor coffee;
- X
- /* text and font will be set in mail_status() */
- Icon mail_icon, compose_icon;
- X
- static Notify_value scroll_hdr();
- X
- make_tool()
- {
- X Rect mrect; /* Position and size of icon label. */
- X struct stat rootbuf, tmpbuf;
- X char *p;
- X struct pixfont *pf_open();
- X
- X if (p = do_set(set_options, "font")) {
- X char buf[MAXPATHLEN];
- X (void) sprintf(buf, "%s%s", FONTDIR, p);
- X if (!(mush_font = pf_open(buf)))
- X print("couldn't open font \"%s\"\nUsing default font.\n", buf);
- X }
- X if (!mush_font)
- X mush_font = pf_default();
- X
- X geticon();
- X check_icons();
- X
- X if (p = do_set(set_options, "screen_win"))
- X screen = atoi(p);
- X else
- X screen = 6;
- X
- X /* where to place text on mail icon -- how many messages there are */
- X mrect.r_left = l_width();
- X mrect.r_top = 58-l_height();
- X mrect.r_width = 3*l_width();
- X mrect.r_height = l_height();
- X (void) icon_set(mail_icon, ICON_LABEL_RECT, &mrect, NULL);
- X
- X (void) window_set(tool,
- X FRAME_ICON, mail_icon,
- X WIN_CONSUME_KBD_EVENTS,
- X WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, NULL,
- X NULL);
- X (void) notify_interpose_destroy_func(tool, destroy_proc);
- X
- X choice_args = panel_make_list(
- X PANEL_MENU_TITLE_FONT, mush_font,
- X PANEL_DISPLAY_LEVEL, PANEL_NONE,
- X PANEL_SHOW_MENU, TRUE,
- X PANEL_SHOW_MENU_MARK, FALSE,
- X NULL);
- X
- X button_args = panel_make_list(
- X PANEL_FEEDBACK, PANEL_INVERTED,
- X PANEL_SHOW_MENU, FALSE,
- X NULL);
- X
- X hdr_panel = make_hdr_panel(tool, choice_args, button_args);
- X
- X make_hdr_sw(tool);
- X
- X main_panel = make_main_panel(tool, choice_args, button_args);
- X
- X /* main mush frame text subwindow for wprint() */
- X mfprint_sw = window_create(tool, TEXTSW,
- X WIN_BELOW, main_panel,
- X WIN_HEIGHT, l_height() * 4,
- X TEXTSW_READ_ONLY, TRUE,
- X TEXTSW_BLINK_CARET, FALSE,
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
- X NULL);
- X /* order is important -- scroll_textwin should be called first! */
- X (void) notify_interpose_event_func(mfprint_sw,
- X fkey_interposer, NOTIFY_SAFE);
- X (void) notify_interpose_event_func(mfprint_sw,
- X scroll_textwin, NOTIFY_SAFE);
- X
- X /* text subwindow for paging messages */
- X p = do_set(set_options, "crt_win");
- X pager_textsw = window_create(tool, TEXTSW,
- X WIN_HEIGHT, l_height() * (p? atoi(p) : 12),
- X TEXTSW_READ_ONLY, TRUE,
- X TEXTSW_BLINK_CARET, FALSE,
- #ifdef SUN_4_0 /* SunOS 4.0+ */
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_WORD,
- #else /* SUN_4_0 */
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
- #endif /* SUN_4_0 */
- X NULL);
- X /* order is important -- scroll_textwin should be called first! */
- X (void) notify_interpose_event_func(pager_textsw,
- X fkey_interposer, NOTIFY_SAFE);
- X (void) notify_interpose_event_func(pager_textsw,
- X scroll_textwin, NOTIFY_SAFE);
- X
- X (void) sprintf(blank, "%128c", ' ');
- X mrect = *(Rect *)window_get(hdr_sw, WIN_RECT);
- X pw_writebackground(hdr_win, 0,0, mrect.r_width, mrect.r_height, PIX_CLR);
- X istool = 2;
- X (void) fclose(stdin);
- X (void) fclose(stdout);
- #ifndef SUN_3_5
- X /* SunOS 3.5 takes tty modes for ttysws from stderr. */
- X (void) fclose(stderr);
- #endif /* SUN_3_5 */
- X (void) do_version();
- X init_cursors();
- X timeout_cursors(TRUE);
- X window_fit_height(tool);
- }
- X
- void
- close_frame()
- {
- X if (do_set(set_options, "compose_icon")) {
- X icon_set(compose_icon, ICON_IMAGE, &compose_icon_image, NULL);
- X window_set(compose_frame, FRAME_CLOSED, TRUE, NULL);
- X } else
- X window_set(compose_frame, WIN_SHOW, FALSE, NULL);
- }
- X
- void
- make_compose_frame()
- {
- X char *p;
- X Textsw msg_sw;
- X Panel panel, make_compose_panel();
- X Notify_value compose_destroy_proc();
- X
- #ifdef SUN_3_5
- X if (nopenfiles(0) < 8) {
- X ok_box("Too many frames; close one, please.\n");
- X compose_frame = 0;
- X return;
- X }
- #endif /* SUN_3_5 */
- X
- X if (do_set(set_options, "compose_icon"))
- X compose_frame = window_create(NULL, FRAME,
- X FRAME_LABEL, "Compose Letter",
- X FRAME_SHOW_LABEL, TRUE,
- X FRAME_NO_CONFIRM, TRUE,
- X FRAME_ICON, compose_icon,
- X WIN_SHOW, TRUE,
- X NULL);
- X else
- X compose_frame = window_create(tool, FRAME,
- X FRAME_LABEL, "Compose Letter",
- X FRAME_SHOW_LABEL, TRUE,
- X FRAME_NO_CONFIRM, TRUE,
- X FRAME_DONE_PROC, close_frame,
- X WIN_SHOW, TRUE,
- X NULL);
- X (void) notify_interpose_destroy_func(compose_frame, compose_destroy_proc);
- X
- X panel = make_compose_panel(compose_frame, choice_args, button_args);
- X
- X /* text subwindow for composing messages */
- X p = do_set(set_options, "msg_win");
- X msg_sw = window_create(compose_frame, TEXTSW,
- X WIN_BELOW, panel,
- X WIN_HEIGHT, l_height() * (p? atoi(p) : 24),
- X TEXTSW_READ_ONLY, TRUE, /* set to false later */
- X TEXTSW_BLINK_CARET, FALSE,
- X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
- X TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
- X NULL);
- X notify_interpose_event_func(msg_sw, fkey_interposer, NOTIFY_SAFE);
- X notify_interpose_event_func(msg_sw, edit_msg_textwin, NOTIFY_SAFE);
- X
- X /* Assign textsw (msg_sw) to panel for panel items' callbacks */
- X panel_set(panel, PANEL_CLIENT_DATA, msg_sw, NULL);
- X
- X /* tty subwindow */
- X if (!(tty_sw = window_create(compose_frame, TTY,
- X TTY_QUIT_ON_CHILD_DEATH, FALSE,
- X TTY_ARGV, TTY_ARGV_DO_NOT_FORK,
- X WIN_CLIENT_DATA, msg_sw,
- X WIN_SHOW, FALSE,
- X WIN_WIDTH, WIN_EXTEND_TO_EDGE,
- X WIN_BELOW, msg_sw,
- X NULL)))
- X perror("tty_sw"), cleanup(0);
- X
- X /* catch SIGTERM when tty_sw dies */
- X (void) signal(SIGTERM, catch);
- X window_fit_height(compose_frame);
- }
- X
- /*ARGSUSED*/
- void
- open_compose()
- {
- X if (compose_frame) {
- X if (do_set(set_options, "compose_icon"))
- X window_set(compose_frame, FRAME_CLOSED, FALSE, NULL);
- X else
- X window_set(compose_frame, WIN_SHOW, TRUE, NULL);
- X } else
- X make_compose_frame();
- }
- X
- void
- destroy_compose()
- {
- X if (!compose_destroy && compose_frame)
- X window_destroy(compose_frame);
- }
- X
- /*ARGSUSED*/
- Notify_value
- compose_destroy_proc(frame, status)
- Frame frame;
- Destroy_status status;
- {
- X if (!compose_destroy && compose_frame) {
- X compose_destroy++;
- X if (ison(glob_flags, IS_GETTING))
- X rm_edfile(-1);
- X }
- X return notify_next_destroy_func(frame, status);
- }
- X
- Panel
- get_compose_panel()
- {
- X Panel panel;
- X
- #ifdef SUN_4_0
- X if (do_set(set_options, "compose_icon"))
- X panel = (Panel)window_get(compose_frame, FRAME_NTH_WINDOW, 0);
- X else
- X panel = (Panel)window_get(compose_frame, FRAME_NTH_WINDOW, 1);
- #else
- X panel = (Panel)window_get(compose_frame, FRAME_NTH_WINDOW, 0);
- #endif /* SUN_4_0 */
- X return panel;
- }
- X
- void
- close_compose(item, value, event)
- Panel_item item;
- int value;
- Event *event;
- {
- X if (event_id(event) == MS_LEFT) {
- X close_frame();
- X return;
- X }
- X switch (value) {
- X case 0:
- X close_frame();
- X when 1:
- X destroy_compose();
- X when 2:
- X (void) help(0, "close", tool_help);
- X }
- }
- X
- parse_tool_opts(argcp, argv)
- int *argcp;
- char **argv;
- {
- X if (!(tool = window_create((Window) 0, FRAME,
- X FRAME_ARGC_PTR_ARGV, argcp, argv,
- X NULL)))
- X cleanup(0);
- }
- X
- /*
- X * used by both the hdr_sw (to scroll canvas) and by textsw's.
- X * Return values:
- X * MUSH_SCROLL_TO (to scroll _to_ a particular location)
- X * MUSH_SCROLL_RELATIVE (scroll relative our current location)
- X * MUSH_SCROLL_IGNORE (not a scroll event and ignore it entirely (up events))
- X * MUSH_SCROLL_PASS_EVENT (not a scroll event; pass it to next event handler)
- X * If absolute scrolling (scroll_to) then "amount" is set to 1 for beginning
- X * of textsw or 2 for end of textsw.
- X * User can precede a keyboard scrolling request by a "count" -- the
- X * count is typed by the user in digits: 5j = move 5 lines down.
- X * It is assumed that if the user moves the mouse after a digit is pressed,
- X * then he doesn't really want to adjust the scrolling amount and the
- X * count is reset to the default (1).
- X */
- Scroll_action
- decode_scroll(client, event, len, amount)
- Notify_client client;
- Event *event;
- int len, *amount;
- {
- X static int count;
- X
- X if (event_id(event) == LOC_MOVE) {
- X count = 0;
- X return MUSH_SCROLL_PASS_EVENT;
- X }
- X
- X *amount = 0; /* Assume relative scroll */
- X if (ID == SCROLL_REQUEST)
- X return MUSH_SCROLL_PASS_EVENT;
- X
- X if (event_is_up(event))
- X return MUSH_SCROLL_PASS_EVENT;
- X if (event_is_ascii(event) && isdigit(event_id(event))) {
- X count = (count * 10) + event_id(event) - '0';
- X return MUSH_SCROLL_IGNORE;
- X }
- #ifdef SUN_4_0 /* SunOS 4.0+ */
- X /* returns sunview events for some ctl chars */
- X switch (event_action(event)) {
- X case ACTION_GO_LINE_FORWARD:
- X case ACTION_GO_COLUMN_FORWARD:
- X *amount = count ? count : 1;
- X count = 0;
- X return MUSH_SCROLL_RELATIVE;
- X case ACTION_GO_LINE_BACKWARD:
- X case ACTION_GO_COLUMN_BACKWARD:
- X *amount = count ? -count : -1;
- X count = 0;
- X return MUSH_SCROLL_RELATIVE;
- X case ACTION_GO_DOCUMENT_START:
- X *amount = 1;
- X count = 0;
- X return MUSH_SCROLL_TO;
- X case ACTION_GO_DOCUMENT_END:
- X *amount = 2;
- X count = 0;
- X return MUSH_SCROLL_TO;
- X }
- #endif /* SUN_4_0 */
- X /* for SunOS 3.5, assume default SunView key mapping */
- X /* a little redundancy for 4.0, but it's ok */
- X if (!event_is_ascii(event) && ID != KEY_RIGHT(14) && ID != KEY_RIGHT(8)
- X && ID != KEY_RIGHT(7) && ID != KEY_RIGHT(13))
- X /* may have to reset "count" here */
- X return MUSH_SCROLL_PASS_EVENT; /* Not a scroll event */
- X switch (event_id(event)) {
- X case KEY_RIGHT(7): /* Home on new keyboards */
- X *amount = 1, count = 0;
- X return MUSH_SCROLL_TO;
- X case KEY_RIGHT(13): /* End on new keyboards */
- X *amount = 2, count = 0;
- X return MUSH_SCROLL_TO;
- X case 'j': case KEY_RIGHT(14): /* downarrow */
- X *amount = count ? count : 1;
- X when 'k': case KEY_RIGHT(8): /* uparrow */
- X *amount = count ? -count : -1;
- X when 'F'-'@': /* ^f */
- X *amount = count ? count * (len-1) : len - 1;
- X when 'D'-'@': /* ^d */
- X *amount = len/2;
- X when 'B'-'@': /* ^b */
- X *amount = -(count ? count * (1-len) : len - 1);
- X when 'U'-'@': /* ^u */
- X *amount = -len/2;
- X when '\033': /* Escape */
- X /* For SunOS 3.5 check to see if this is a cursor
- X * move key, i.e. ESC[A or ESC[B.
- X */
- X if (!(int)window_read_event(client, event) &&
- X event_id(event) == '[' &&
- X !(int)window_read_event(client, event))
- X if (event_id(event) == 'A') {
- X *amount = -1;
- X break;
- X } else if (event_id(event) == 'B') {
- X *amount = 1;
- X break;
- X }
- X default:
- X count = 0;
- X return event_is_ascii(event) ?
- X MUSH_SCROLL_IGNORE : MUSH_SCROLL_PASS_EVENT;
- X }
- X count = 0;
- X /* Scroll indicated amount if event is down, ignore up events */
- X return MUSH_SCROLL_RELATIVE;
- }
- X
- Notify_value
- scroll_textwin(textsw, event, arg, type)
- Textsw textsw;
- Event *event;
- Notify_arg arg;
- Notify_event_type type;
- {
- X int scroll_amount;
- X
- X switch (decode_scroll(textsw, event, textsw_screen_line_count(textsw),
- X &scroll_amount)) {
- X case MUSH_SCROLL_PASS_EVENT :
- X return notify_next_event_func(textsw, event, arg, type);
- X case MUSH_SCROLL_IGNORE:
- X return NOTIFY_IGNORED;
- X case MUSH_SCROLL_TO:
- X if (scroll_amount == 1)
- X window_set(textsw, TEXTSW_FIRST, 0, NULL);
- X else if (scroll_amount == 2)
- X window_set(textsw, TEXTSW_FIRST, TEXTSW_INFINITY, NULL);
- X textsw_scroll_lines(textsw, -textsw_screen_line_count(textsw));
- X break;
- X case MUSH_SCROLL_RELATIVE :
- X textsw_scroll_lines(textsw, scroll_amount);
- X }
- X window_set(textsw, TEXTSW_UPDATE_SCROLLBAR, NULL);
- X return NOTIFY_DONE;
- }
- X
- /*ARGSUSED*/
- Notify_value
- destroy_proc(frame, status)
- Frame frame;
- Destroy_status status;
- {
- X if (ison(glob_flags, IS_GETTING))
- X rm_edfile(-1);
- X /* status is ignored -- maybe post notice asking to confirm quit? */
- X if (status == DESTROY_CHECKING && ison(glob_flags, DO_UPDATE) &&
- X !ask("Your folder has been modified. Quit anyway?"))
- X (void) notify_veto_destroy(frame);
- X else
- X cleanup(0); /* doesn't return */
- X return NOTIFY_DONE;
- }
- X
- /* Initialise the Mush mail icon. */
- static void
- geticon()
- {
- X static Rect lrect = { 5, 5, 26, 12 };
- X
- X mail_icon = icon_create(
- X ICON_WIDTH, 64,
- X ICON_HEIGHT, 64,
- X ICON_FONT, mush_font,
- X ICON_IMAGE, &mail_icon_image1,
- X ICON_LABEL, "",
- X ICON_LABEL_RECT, &lrect,
- X 0);
- X compose_icon = icon_create(
- X ICON_WIDTH, 64,
- X ICON_HEIGHT, 64,
- X ICON_IMAGE, &compose_icon_image,
- X ICON_LABEL, "",
- X 0);
- }
- X
- /* Initialise all the cursors used. */
- static void
- init_cursors()
- {
- X extern Pixrect mouse_left, mouse_middle, mouse_right, bent_arrow;
- X extern Cursor bentarrow;
- X
- X l_cursor = cursor_create(
- X CURSOR_XHOT, 3,
- X CURSOR_YHOT, 3,
- X CURSOR_OP, PIX_SRC,
- X CURSOR_IMAGE, &mouse_left,
- X NULL);
- X m_cursor = cursor_create(
- X CURSOR_XHOT, 3,
- X CURSOR_YHOT, 3,
- X CURSOR_OP, PIX_SRC,
- X CURSOR_IMAGE, &mouse_middle,
- X NULL);
- X r_cursor = cursor_create(
- X CURSOR_XHOT, 3,
- X CURSOR_YHOT, 3,
- X CURSOR_OP, PIX_SRC,
- X CURSOR_IMAGE, &mouse_right,
- X NULL);
- X bentarrow = cursor_create(
- X CURSOR_XHOT, 8,
- X CURSOR_YHOT, 8,
- X CURSOR_OP, PIX_SRC|PIX_DST,
- X CURSOR_IMAGE, &bent_arrow,
- X NULL);
- X coffee = cursor_create(
- X CURSOR_XHOT, 8,
- X CURSOR_YHOT, 8,
- X CURSOR_OP, PIX_SRC,
- X CURSOR_IMAGE, &coffee_cup,
- X NULL);
- }
- X
- /* show the timeout cursor (coffee cup) when "on" is TRUE. This routine
- X * may be called many times in layers of locking mechanisms, so be careful
- X * not to unlock cursors until "on" has been FALSE as many times as it has
- X * been TRUE.
- X */
- void
- timeout_cursors(on)
- int on;
- {
- X Window win;
- X Frame subframe;
- X static int locked, numwins;
- X int i = 0, j;
- X static struct {
- X Cursor cursor;
- X Window win;
- X } win_curs[64];
- X
- X on? locked++ : locked--;
- X if (istool < 2 || locked > 1 || locked == 1 && on == 0)
- X return;
- X if (on) {
- X for (numwins = 0; win = window_get(tool, FRAME_NTH_SUBWINDOW, numwins);
- X numwins++) {
- X win_curs[numwins].cursor =
- X cursor_copy((Cursor) window_get(win, WIN_CURSOR));
- X win_curs[numwins].win = win;
- X window_set(win, WIN_CURSOR, coffee, NULL);
- X }
- X while (subframe = window_get(tool, FRAME_NTH_SUBFRAME, i++))
- X for (j = 0; win = window_get(subframe, FRAME_NTH_SUBWINDOW, j);
- X j++,numwins++) {
- X win_curs[numwins].cursor =
- X cursor_copy((Cursor) window_get(win, WIN_CURSOR));
- X win_curs[numwins].win = win;
- X window_set(win, WIN_CURSOR, coffee, NULL);
- X }
- X } else {
- X for (j = 0; j < numwins; j++) {
- X window_set(win_curs[j].win, WIN_CURSOR, win_curs[j].cursor, NULL);
- X cursor_destroy(win_curs[j].cursor);
- X }
- X }
- }
- X
- /*
- X * If the user has specified an alternate icon or set of icons in
- X * his .mushrc file, copy the image(s) over the defaults.
- X */
- void
- check_icons()
- {
- X Pixrect *icon_mpr;
- X char errbuf[256], *icon_file, *icon_path;
- X int isdir;
- X
- X if ((icon_file = do_set(set_options, "mail_icon")) && *icon_file) {
- X isdir = 0;
- X icon_path = getpath(icon_file, &isdir);
- X if (isdir == 0) {
- X if (!(icon_mpr = icon_load_mpr(icon_path, errbuf)))
- X error("Error loading mail icon file:\n%s",errbuf);
- X else
- X pr_rop(&mail_icon_image1, 0,0,64,64, PIX_SRC, icon_mpr, 0, 0);
- X }
- X }
- X if ((icon_file = do_set(set_options, "newmail_icon")) && *icon_file) {
- X isdir = 0;
- X icon_path = getpath(icon_file, &isdir);
- X if (isdir == 0) {
- X if (!(icon_mpr = icon_load_mpr(icon_path, errbuf)))
- X error("Error loading newmail icon file:\n%s",errbuf);
- X else
- X pr_rop(&mail_icon_image2, 0,0,64,64, PIX_SRC, icon_mpr, 0, 0);
- X }
- X }
- X if ((icon_file = do_set(set_options, "compose_icon")) && *icon_file) {
- X isdir = 0;
- X icon_path = getpath(icon_file, &isdir);
- X if (isdir == 0) {
- X if (!(icon_mpr = icon_load_mpr(icon_path, errbuf)))
- X error("Error loading newmail icon file:\n%s",errbuf);
- X else
- X pr_rop(&compose_icon_image, 0,0,64,64, PIX_SRC, icon_mpr, 0, 0);
- X }
- X }
- }
- SHAR_EOF
- chmod 0644 tool.c ||
- echo 'restore of tool.c failed'
- Wc_c="`wc -c < 'tool.c'`"
- test 16831 -eq "$Wc_c" ||
- echo 'tool.c: original size 16831, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= tool_help ==============
- if test -f 'tool_help' -a X"$1" != X"-c"; then
- echo 'x - skipping tool_help (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting tool_help (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'tool_help' &&
- @(#)tool_help (c) copyright 10/18/86 (Dan Heller)
- X
- %general%
- X
- X IF ALL ELSE FAILS, READ THE DIRECTIONS!
- X
- This famous quote applies here more than ever. If
- you are unfamiliar with Mushview, you should get
- yourself acquainted with it by choosing HELP options
- in menu items. If you get frustrated or confused
- about how to use or run a command, or if you want to
- know how something works or get to know quick shortcuts
- in achieving tasks, it is advisable to look at the
- Help option available with some items.
- %%
- X
- %help%
- Help was designed for users to get help from all commands
- and options. The last item in many menus is a "help"
- choice. You will get an appropriate help message describing
- what you can do at the position you are in on the Mushview
- window.
- X
- If a help message isn't much help, it may be more helpful to
- reference a different help item which describes in more detail
- what you want to know. For example, reading the help for
- "folder" will help you better understand the method in which
- mail messages are stored than it would if you had read the help
- message for "save" first.
- %%
- X
- %mouse%
- The mouse is an image (cursor) which moves across the screen. Its
- position indicates which window is to receive input when you type
- or click a mouse button.
- X
- The mouse may take upon different images which indicate various
- things. When the image looks like a "coffee cup", Mushview is in
- the process of doing something, like sending mail, or reading in
- new mail. In this event, you should wait till the cursor returns
- to its normal state before attempting to do anything else. Go get
- some coffee.
- X
- When in the Header Window, the cursor will look like the mouse
- device that you hold with the buttons flashing on and off. This
- is to remind you that you can use each button to do different tasks.
- Using the RIGHT mouse button gives you a menu of options to do for
- the message under the mouse.
- %%
- X
- %respond%
- This item responds to mail in 4 ways.
- In all cases, at least one recipient of your message will be the
- sender of the message you are responding to. If a subject was in
- the author's letter, then it will be used as your subject.
- X
- The first and most used method of response is to the author of the
- message only. Selecting this item with the LEFT mouse button will
- use this method for responding to mail.
- X
- If you want to include a copy of the author's message, then choose
- the menu item which says to include the message. If you wish for
- all the recipients of the message to receive a copy of your reply,
- then choosing the third item will include them.
- X
- The fourth menu item will mail to the author and everyone listed on
- the To and Cc lines of the message, and include the message you are
- responding to in your text.
- X
- In such cases where you include the message you are responding to,
- the included message will be indented by "> " to identify it from
- your message. If you would like to have a string other than the
- default used, then set the appropriate option to whatever you would
- prefer by selecting the "Opts" item, moving the mouse on top of the
- string, "indent-str", selecting the LEFT mouse button and typing the
- desired string.
- %%
- X
- %delete%
- You may delete or undelete messages with this item.
- When using the LEFT mouse button, you will delete the
- current message (HIGHLIGHTED in the headers' window).
- Otherwise, you may select the menu item for undelete.
- X
- You may delete or undelete a "range" of messages by
- typing the range in the Header Window.
- X
- For help on valid message ranges, select the menu in
- the area marked "range" in the Header Panel Window.
- %%
- X
- %folder%
- Your "folder" is a place to keep all your individual messages. Usually,
- if you are a heavy mail user, you would organize your mail in such a
- way in which related mail would be saved together in one folder. You
- create folders simply by saving mail to a filename. Additional mail
- can be saved to those files in the same way. To manipulate messages
- in folders, you "change folders" to the folder you wish to access
- using the folder item. Since it may occur that you switch back and
- forth between two folders, you may use the previous folder menu item
- which updates changes made to the current folder and changes your
- folder to the one previous to the current.
- X
- You may also select the exact name of the folder you wish to access
- by selecting the left mouse button on the "folder" item and TYPING
- the exact name of the folder you wish to access. The "pathname" to
- the folder may start with a tilde (~) indicating your home directory.
- Or, it may contain a plus sign before the name indicating your Mail
- directory (+reports, for example). Alternatively, you can type '%'
- to access your system Mailbox, the place where all your mail is first
- delivered. And finally, you can type '#' to indicate the previously
- accessed folder.
- %%
- X
- %save%
- You may save messages in two ways. The most commonly used method is to
- save messages to your mailbox folder ("mbox") in your home directory.
- If you use mail very frequently and save large amounts of mail, you can
- save messages to other folders for better organization.
- X
- Usually, when messages are saved, mushtool marks them for deletion for
- the next update. If you don't want to have saved messages deleted, you
- must undelete them or set the variable "keepsave" in the options screen.
- X
- There is a text item in the Main Panel Window which allows you to type
- the name of the file to save a message. Type the filename and then
- select the LEFT mouse button over the "Save" item. If there is no
- filename specified, then messages are saved to your mbox file.
- X
- You may also choose a folder name by selecting the RIGHT mouse button
- over the "Save" item and choosing from the menu of files displayed.
- X
- You can specify a range, or group of messages to save by typing a range
- in the Header Panel Window. If there is a message list in that panel
- item, then the range of messages specified there will be saved. If not,
- the current message will be saved.
- X
- For additional information, see the help option for Folders.
- %%
- X
- %quit%
- There are various ways in which you may be finished with Mushview.
- The most commonly used method is to simply "close" the tool to an
- iconic form. This means that you haven't really quit, but you have
- merely put it on "hold" till later. It will become an icon on the
- side or corner of the screen and appear to sit and do nothing. To
- close the tool to icon form, there are two methods which have will
- have two different effects.
- X
- The first method is to select this panel item with the left mouse
- button. This will update your current folder (deleting messages
- marked for deletion) and close the tool. The second method is to
- use the tool manager around the perimeter of the window and select
- "close". This will close the tool without updating your mailfile.
- X
- Whenever Mushview is in the "closed" state, it periodically
- checks your mail and updates your folder with the new mail. While
- Mushview is in iconic form, it will display the number of messages
- you have in the current folder.
- X
- There are two equally similar methods of exiting Mushview, rather
- than just closing to an icon: you may select the second menu item
- in the menu given by this panel item or you may use the tool mana-
- ger "quit" item.
- X
- Using the tool manager's quit will exit the tool without updating
- your folder whereas the panel item's menu selection will have the
- Mushview prompt you whether to update the current folder or not.
- %%
- X
- %update%
- This item will update the current folder you are using. Changes are
- updated to the folder; that is, deleted mail is removed and all other
- mail is copied back to the folder unless otherwise specified. See the
- help in "folder" for more information on folders.
- X
- If new mail has arrived, it will incorporate it. Otherwise, new mail
- is incorporated every two minutes or so, if some comes in.
- %%
- X
- %headers%
- The message headers are displayed in their own separate window.
- The "current" message is usually displayed in either BOLD or
- REVERSE text. This "highlighted" message is the one which is
- displayed at the bottom, larger window. In the message window,
- each message is displayed in the following format:
- the message number is displayed first; if it is the "current"
- message, then there is a '>' sign.
- The next character is the 'status' character:
- X 'N' -- New (and unread)
- X 'U' -- not new, but still Unread
- X '*' -- delete messages (set show_deleted)
- X 'P' -- preserve in spoolfile.
- X 'O' -- Old message which has also been Read.
- If there is just a space (no character), the message is new, but
- you've already read it. You should explicitly save or delete these.
- X
- Following that is the Author of the message and/or all or part of
- his network address and login name. Following that is the number
- of lines the message is. In quotes is all or part of the "Subject"
- (if one was specified).
- X
- To read a message, select either the READ item in the main panel
- subwindow or move the mouse over the message header you want to read
- and press the LEFT mouse button. Or, the MIDDLE mouse button will
- delete that message. Choosing the RIGHT mouse button will give you
- SHAR_EOF
- true || echo 'restore of tool_help failed'
- fi
- echo 'End of part 21'
- echo 'File tool_help is continued in part 22'
- echo 22 > _shar_seq_.tmp
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-